/**********************************************************************************
 * Code license:  GNU General Public License v3                                   *
 * Main page:     https://code.google.com/p/library-cross-platform/               *
 * Issue tracker: https://code.google.com/p/library-cross-platform/issues/list    *
***********************************************************************************/
package library.classloader;

import java.io.*;
import java.util.*;
import library.util.resources.*;

@SuppressWarnings({ "rawtypes", "unchecked" })
public class JarClassLoader extends ClassLoader {

  private JarResourcesLoader jarResources;
  private Hashtable          loadedClasses = new Hashtable();


  public JarClassLoader(String jarName) throws NullPointerException, FileNotFoundException, IOException{
     jarResources = new JarResourcesLoader(jarName);
     jarResources.load();
  }
  
  public List getContent() {
    return jarResources.getContent();
  }
    
  protected String formatClassName(String className) {
     return className.replace('.', File.separatorChar) + ".class";
  }

  
  protected byte[] loadClassBytes(String className) {
      className = formatClassName(className);
      return (jarResources.getResource(className));
  }

  public synchronized Class loadClass(String aClassName) throws ClassNotFoundException {
      return (loadClass(aClassName, true));
  }

  public synchronized Class loadClass(String className, boolean resolveNow) throws ClassNotFoundException {
      Class result;
      byte[] classBytes;
      result = (Class) loadedClasses.get(className);
      if (result != null)
          return result;

      try {
        result = super.findSystemClass(className); /* if class was not found then ClassNotFoundException ocured */
        return result;
      } catch (ClassNotFoundException e) {}

      classBytes = loadClassBytes(className);
      if (classBytes == null) {
          throw new ClassNotFoundException();
      }

      result = defineClass(null, classBytes, 0, classBytes.length, null);
      if (result == null)
          throw new ClassFormatError();
      
      if (resolveNow)
        resolveLoadedClass(result);

      loadedClasses.put(className, result);
      return result;
  }

  public void resolveLoadedClass(Class c) throws NullPointerException {
    this.resolveClass(c);
  }

}